package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectDemo3 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Person p = new Person("李四");
        System.out.println(p);

        // 1. 获取类对象：`Class.forName("reflect.Person")`
        // 2. 通过类对象获取特定的构造器：`getConstructor(参数类型列表)`
        // 3. 通过构造器对象创建实例：`newInstance(实际参数)`


        //总结流程
        //定位类：通过全限定名获取Class对象
        //
        //定位构造方法：根据参数类型获取Constructor对象
        //
        //准备参数：创建与构造方法签名匹配的参数值数组
        //
        //创建实例：调用Constructor的newInstance方法
        //
        //使用对象：将返回的Object转换为具体类型并操作


 //     步骤	                              代码	                           含义
//1. 加载类	            Class cls = Class.forName("Reflect.Person");	动态加载类并获取 Class 对象
//2. 获取构造方法  Constructor c = cls.getConstructor(String.class);	 获取带 String 参数的 public 构造方法
//3. 创建对象	Object obj = c.newInstance("王五");	               调用构造方法创建对象，传入参数 "王五"

        Class cls = Class.forName("reflect.Person");
        Constructor c = cls.getConstructor(String.class);
        Object obj = c.newInstance("王五");
        System.out.println(obj);

//1. `Class.forName("reflect.Person")`：通过类的全限定名（包括包名）获取该类的Class对象。
// 2. `cls.getConstructor(String.class)`：获取一个公开的（public）构造器，该构造器接受一个String类型的参数。
//    这里`String.class`是String类型的Class对象，用于指定参数类型。
// 3. `c.newInstance("王五")`：通过上一步获取的构造器对象来创建实例。传入的实际参数是一个字符串"王五"。
// 注意：
//   - 如果`reflect.Person`类没有无参构造器，或者没有匹配的构造器，则会抛出异常（例如`NoSuchMethodException`）。
//   - 通过构造器对象创建实例可以避免使用无参构造器，而是使用我们指定的构造器。
// 等价于非反射代码：
//     Person obj = new Person("王五");
// 但是反射方式允许我们在运行时动态地决定使用哪个类以及哪个构造器，这增加了灵活性。
        Constructor c2 = cls.getConstructor(String.class,int.class);
        //public Constructor<T> getConstructor(Class<?>... parameterTypes)
        Object obj2 = c2.newInstance("赵六",34);
        System.out.println(obj2);

        Class cls2 = Class.forName("reflect.Student");
        Constructor c3 = cls2.getConstructor(String.class,int.class);
        Object obj3 =c3.newInstance("流域",33);
        System.out.println(obj3);

    }


}
